home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 1 / PC Actual CD 01.iso / share / dos / demos / planets / source.lzh / MAKEXION.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-28  |  6.3 KB  |  211 lines

  1.  
  2. /*
  3.  *  MAKEXION.C
  4.  *
  5.  *  (Simon Hern, 1994)
  6.  *
  7.  *  Create compleXion data file for Bouncing Planets demo
  8.  *
  9.  *  The Xion is generated randomly and written to the file XION.DAT
  10.  *  It's destined to become the surface of a planet (mercator map)
  11.  *  Uses sort-of-ish fractal generation on a spherical surface
  12.  *  The result is a RHO by 2*RHO bitmap in up to 256 colours
  13.  *
  14.  *  For speed, uses an assembler language function from XIONCODE.ASM
  15.  *
  16.  */
  17.  
  18.  
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <time.h>
  23. #include <math.h>
  24.  
  25. /* XLib v06 */
  26. #include <xfileio.h>
  27.  
  28. /* Local definitions (notably RHO: the surface resolution) */
  29. #include "planet.h"
  30.  
  31.  
  32.  
  33. /* Routine to displace an area of landscape (in XIONCODE.ASM) */
  34. extern void fracture(int rf_num, int blast, int x_start);
  35.  
  36.  
  37. /* Save 'far' arrays of data */
  38. int far_save(char * fname, char far * data, unsigned len);
  39.  
  40.  
  41.  
  42. /* Surface generation parameters: */
  43. /* Strength of first break, and exponential decay of strength */
  44. #define FULL_BLAST 20.0
  45. #define POWER 3.0
  46.  
  47. /* Final xion data scaled so altitudes lie between two extreme values */
  48. /* (This in effect defines the palette colours used for the final planet) */
  49. #define DEEPEST 1
  50. #define HIGHEST 80
  51.  
  52. /* File to write data to */
  53. #define XION_FILE "XION.DAT"
  54.  
  55.  
  56.  
  57. /* Precalculated values determining where landscape cracks */
  58. /* (This is used by the external 'fracture' function) */
  59. char riff[RHO/2][RHO/2];
  60.  
  61. /* The (full size) skin array in which the surface is generated */
  62. /* (This array is a bit of a pain - it's exactly 64k long, and since it's */
  63. /*  global it bloats the size of the compiled code. But the data needs an */
  64. /*  entire memory segment to itself and dynamic memory allocation isn't */
  65. /*  particularly sympathetic to that. I've given up fighting it.) */
  66. int huge skin[RHO][2*RHO];
  67.  
  68.  
  69.  
  70. void main() {
  71.  
  72.     int strike;          /* Number of fractures to make */
  73.     int displac = 0;     /* Move everything upwards; rebalance later */
  74.  
  75.     int blast;           /* Depth of next fracture */
  76.     int rf_num;          /* Riff to use on this fracture */
  77.     int r1;              /* Preliminary random choice of riff */
  78.     int half;            /* Random choice of which half of surface to hit */
  79.     int dirn;            /* Random choice of whether to blast up or down */
  80.     int x_start;         /* Position around equator to start at */
  81.     float r2, dis;       /* Weight riff probabilities */
  82.  
  83.     float w, sig, gam;   /* Partial calculations during riff formation */
  84.  
  85.     int x, y;            /* Every program needs some x and y coordinates */
  86.     int max, min;        /* Maximum and minimum heights */
  87.     int hgt;             /* A height (for temporary purposes) */
  88.  
  89.     /* Final resting place of the xion data (after rescaling) */
  90.     /* (Byte-size values rather than word-size values) */
  91.     unsigned char xion[RHO][2*RHO];
  92.  
  93.  
  94.  
  95.     randomize();
  96.  
  97.  
  98.   /* Generate the riff data (mathematical gibberish) */
  99.     printf("Composing riffs\n");
  100.     for ( y = 0 ; y < RHO/2 ; y++ ) {
  101.         for ( x = 0 ; x < RHO/2 ; x++ ) {
  102.             w = ( y + 0.5 ) * PI / RHO;
  103.             sig = ( x + 0.5 ) * PI / RHO;
  104.             gam = atan( tan(w) * cos(sig) );
  105.             riff[y][x] = RHO/2 - (char)floor( gam * RHO/PI + 0.5 );
  106.         }
  107.     }
  108.  
  109.  
  110.  
  111.   /* Generate the surface */
  112.     printf("Making %.0f fractures\n", pow((double)FULL_BLAST,(double)POWER));
  113.  
  114.     for ( strike = pow( (double)FULL_BLAST, (double)POWER )
  115.                     ; strike >= 1 ; strike-- ) {
  116.         blast = FULL_BLAST / pow( (double)strike, (double)1.0/POWER );
  117.  
  118.       /* All the random bits together */
  119.         r1 = random(RHO/2);
  120.         half = random(2);
  121.         dirn = random(2);
  122.         r2 = ((float)rand())/(float)RAND_MAX;  /* between 0 and 1 */
  123.         x_start = random(2*RHO);
  124.  
  125.       /* Balance choice of riffs evenly over the surface */
  126.         dis = sin( PI * (r1+0.5) / RHO );
  127.         if ( r2 <= dis*dis ) rf_num = r1;
  128.         else rf_num = RHO/2 - 1 - r1;
  129.  
  130.       /* We only displace the northern half, then make up for it at the end */
  131.         if ( dirn == 0 ) blast = -blast;
  132.         if ( half == 0 ) displac = displac - blast;
  133.  
  134.       /* Use riff 'rf_num' to displace an area of the surface by */
  135.       /*  depth 'blast', starting at position 'x_start'          */
  136.       /* (Warning: This function only allows RHO to be 128)      */
  137.  
  138.         fracture(rf_num, blast, x_start);
  139.  
  140.       /* The 'fracture' function does something like this:
  141.        *
  142.        *   int x1, x2, x3, x4;
  143.        *   for ( x = 0 ; x < 64 ; x++ ) {
  144.        *       x1 = ( x_start + x ) & 255;
  145.        *       x2 = ( x_start + 255 - x ) & 255;
  146.        *       for ( y = 0 ; y < riff[rf_num][x] ; y++ ) {
  147.        *           skin[y][x1] += blast;
  148.        *           skin[y][x2] += blast;
  149.        *       }
  150.        *       x3 = ( x_start + 128 + x ) & 255;
  151.        *       x4 = ( x_start + 127 - x ) & 255;
  152.        *       for ( y = 0 ; y < 127 - riff[rf_num][x] ; y++ ) {
  153.        *           skin[y][x3] += blast;
  154.        *           skin[y][x4] += blast;
  155.        *       }
  156.        *   }
  157.        */
  158.  
  159.         if ( !(strike%10) ) printf("   Strike: %d      \r", strike);
  160.     }
  161.  
  162.  
  163.  
  164.   /* Find max and min heights */
  165.     max = min = 0;
  166.     for ( y = 0 ; y < RHO ; y++ ) {
  167.         for ( x = 0 ; x < 2*RHO ; x++ ) {
  168.             hgt = ( skin[y][x]+=displac );
  169.             if ( min > hgt ) min = hgt;
  170.             if ( max < hgt ) max = hgt;
  171.         }
  172.     }
  173.     printf("Max: %d   Min: %d      \n", max, min);
  174.  
  175.   /* Rescale skin to make xion */
  176.     printf("Rescaling\n");
  177.     for ( y = 0 ; y < RHO ; y++ ) {
  178.         for ( x = 0 ; x < 2*RHO ; x++ ) {
  179.             xion[y][x] = DEEPEST + (float)(HIGHEST - DEEPEST) *
  180.                         (float)(skin[y][x] - min) / (float)(max - min);
  181.         }
  182.     }
  183.  
  184.  
  185.  
  186.   /* Save the complexion */
  187.     if ( ! far_save(XION_FILE, (char far *)xion, 2*RHO*RHO) ) {
  188.         printf("ERROR: Cannot create file %s\n", XION_FILE);
  189.         exit(1);
  190.     }
  191.  
  192. }
  193.  
  194.  
  195.  
  196. /* Function to save data from a 'far' array (up to 65535 bytes) */
  197.  
  198. int far_save(char * fname, char far * data, unsigned len) {
  199.     int fout;
  200.  
  201.     fout = f_open(fname, F_WRONLY);
  202.     if ( fout == FILE_ERR ) return 0;
  203.  
  204.     f_writefar(fout, data, len);
  205.  
  206.     f_close(fout);
  207.     return 1;
  208. }
  209.  
  210.  
  211.